// JwtUtils.java
package com.qk.common.utils;

import com.qk.common.properties.JwtProperties;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Map;

/**
 * JWT工具类 - 基于jjwt库实现
 */
@Component
public class JwtUtils {
    
    private static final Logger log = LoggerFactory.getLogger(JwtUtils.class);


    // 直接使用实例注入而非静态变量
    @Autowired
    private  JwtProperties jwtProperties;



    /**
     * 生成JWT Token
     */
    public  String generateToken(Map<String, Object> claims) {
        return generateToken(claims, jwtProperties.getSecret(), jwtProperties.getExpiration());
    }

    /**
     * 生成JWT Token
     */
    public  String generateToken(Map<String, Object> claims, String secret, long expiration) {
        try {
            SecretKey key = generateKey(secret);
            Date now = new Date();
            Date expirationDate = new Date(now.getTime() + expiration);

            return Jwts.builder()
                    .setClaims(claims)
                    .setIssuedAt(now)
                    .setExpiration(expirationDate)
                    .signWith(SignatureAlgorithm.HS256, key)
                    .compact();
        } catch (Exception e) {
            log.error("生成JWT Token失败", e);
            throw new RuntimeException("生成JWT Token失败", e);
        }
    }

    /**
     * 解析JWT Token
     */
    public  Claims parseToken(String token) {
        return parseToken(token, jwtProperties.getSecret());
    }

    /**
     * 解析JWT Token
     */
    public  Claims parseToken(String token, String secret) {
        try {
            SecretKey key = generateKey(secret);
            return Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException e) {
            log.debug("JWT Token已过期: {}", token);
            throw e;
        } catch (UnsupportedJwtException e) {
            log.warn("不支持的JWT Token格式: {}", token);
            throw e;
        } catch (MalformedJwtException e) {
            log.warn("JWT Token格式错误: {}", token);
            throw e;
        } catch (SignatureException e) {
            log.warn("JWT Token签名验证失败: {}", token);
            throw e;
        } catch (IllegalArgumentException e) {
            log.warn("JWT Token为空或无效: {}", token);
            throw e;
        }
    }

    /**
     * 验证token是否有效
     */
    public  boolean validateToken(String token) {
        return validateToken(token, jwtProperties.getSecret());
    }

    /**
     * 验证token是否有效
     */
    public  boolean validateToken(String token, String secret) {
        try {
            parseToken(token, secret);
            return !isTokenExpired(token);
        } catch (ExpiredJwtException e) {
            return false;
        } catch (JwtException | IllegalArgumentException e) {
            log.debug("JWT验证失败: {}", e.getMessage());
            return false;
        }
    }

    /**
     * 从token中获取特定声明值
     */
    public  Object getClaimFromToken(String token, String claimName) {
        try {
            Claims claims = parseToken(token);
            return claims.get(claimName);
        } catch (Exception e) {
            log.debug("从Token获取声明失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 检查token是否过期
     */
    public  boolean isTokenExpired(String token) {
        try {
            Claims claims = parseToken(token);
            Date expiration = claims.getExpiration();
            return expiration.before(new Date());
        } catch (ExpiredJwtException e) {
            return true;
        } catch (Exception e) {
            log.debug("检查Token过期状态失败: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 生成安全的SecretKey
     */
    private  SecretKey generateKey(String secret) {
        try {
            byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
            if (keyBytes.length < 32) {
                MessageDigest sha = MessageDigest.getInstance("SHA-256");
                keyBytes = sha.digest(keyBytes);
            }
            return Keys.hmacShaKeyFor(keyBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("生成密钥失败", e);
        }
    }
}
